local jLootz = jLootz
local player = UnitName("player")
local Deformat
do
-- This is very much a rippof of Deformat, simplified in that it does not
-- handle merged patterns
	local select = select
	local tonumber = tonumber
	local string_match = string.match
	local function donothing() end
	
	local sequences = {
		["%d*d"] = "%%-?%%d+",
		["s"] = ".+",
		["[fg]"] = "%%-?%%d+%%.?%%d*",
		["%%%.%d[fg]"] = "%%-?%%d+%%.?%%d*",
		["c"] = ".",
	}
	
	local function get_first_pattern(s)
		local first_pos, first_pattern
		for pattern in pairs(sequences) do
			local pos = s:find("%%%%"..pattern)
			if pos and (not first_pos or pos < first_pos) then
				first_pos, first_pattern = pos, pattern
			end
		end
		return first_pattern
	end
	
	local function get_indexed_pattern(s, i)
		for pattern in pairs(sequences) do
			if s:find("%%%%" .. i .. "%%%$" .. pattern) then
				return pattern
			end
		end
	end

	local function bubble(f, i, a1, ...)
		if f[i] then a1 = tonumber(a1) end
		if not ... then return a1 end
		return a1, bubble(f, i + 1, ...)
	end
	
	local function bubble_num(f, o, i, ...)
		if not o[i] then return end
		local a1 = select(o[i], ...)
		if f[i] then a1 = tonumber(a1) end
		return a1, bubble_num(f, o, i + 1, ...)
	end
	
	local function unpattern_unordered(unpattern, f)
		local i = 1
		while true do
			local pattern = get_first_pattern(unpattern)
			if not pattern then return unpattern, i > 1 end
			
			unpattern = unpattern:gsub("%%%%" .. pattern, "(" .. sequences[pattern] .. ")", 1)
			f[i] = (pattern ~= "c" and pattern ~= "s")
			i = i + 1
		end
	end
	
	local function unpattern_ordered(unpattern, f)
		local i = 1
		while true do
			local pattern = get_indexed_pattern(unpattern, i)
			if not pattern then return unpattern, i > 1 end

			unpattern = unpattern:gsub("%%%%" .. i .. "%%%$" .. pattern, "(" .. sequences[pattern] .. ")", 1)
			f[i] = (pattern ~= "c" and pattern ~= "s")
			i = i + 1
		end
	end

	local function curry(pattern)
		local unpattern, f, matched = '^' .. pattern:gsub("([%(%)%.%*%+%-%[%]%?%^%$%%])", "%%%1") .. '$', {}
		if not pattern:find("%1$", nil, true) then
			unpattern, matched = unpattern_unordered(unpattern, f)
			if not matched then
				return donothing
			else
				return function(text)
					return bubble(f, 1, string_match(text, unpattern))
				end
			end
		else
			unpattern, matched = unpattern_ordered(unpattern, f)
			if not matched then
				return donothing
			else
				local i, o = 1, {}
				pattern:gsub("%%(%d)%$", function(w) o[i] = tonumber(w); i = i + 1; end)
				return function(text)
					return bubble_num(f, o, 1, string_match(text, unpattern))
				end
			end
		end
	end

	local patterns = setmetatable({}, {
		__index = function (self, pattern)
			local c = curry(pattern)
			self[pattern] = c
			return c
		end,
	})
	
	Deformat = function (string, pattern)
		return patterns[pattern](string)
	end
end

local frame = CreateFrame("Frame")
local events = LibStub("CallbackHandler-1.0"):New(jLootz)
--[[
local old_Fire = events.Fire
function events:Fire(event, ...)
	jLootz:Print(event, ...)
	return old_Fire(self, event, ...)
end
]]

frame:SetScript("OnEvent", function (self, event, ...)
	local handler = self[event]
	if handler then
		return handler(self, ...)
	else
		-- pass the event
		events:Fire(event, ...)
	end
end)

local getcoins
do
	local cg = strreplace(GOLD_AMOUNT, '%d', '(%d+)')
	local cs = strreplace(SILVER_AMOUNT, '%d', '(%d+)')
	local cc = strreplace(COPPER_AMOUNT, '%d', '(%d+)')
	local match = string.match

	getcoins = function (s)
		local t, r = match(s, cg)
		r = t and t * 10000 or 0
		t = match(s, cs)
		if t then r = r + t * 100 end
		t = match(s, cc)
		return t and r + t or r
	end
end

local handle = function (self, event, func, ...)
	if ... then
		events:Fire(event, func(...))
		return true
	end
end

local roll_handlers = {
	{ LOOT_ROLL_GREED_SELF, function (what) return "greed", player, what end},
	{ LOOT_ROLL_GREED, function (who, what) return "greed", who, what end},
	{ LOOT_ROLL_NEED_SELF, function (what) return "need", player, what end},
	{ LOOT_ROLL_NEED, function (who, what) return "need", who, what end},
	{ LOOT_ROLL_PASSED_SELF, function (what) return "pass", player, what end},
	{ LOOT_ROLL_PASSED_SELF_AUTO, function (what) return "pass", player, what end},
	{ LOOT_ROLL_PASSED, function (who, what) return "pass", who, what end},
	{ LOOT_ROLL_PASSED_AUTO, function (who, what) return "pass", who, what end},
	{ LOOT_ROLL_PASSED_AUTO_FEMALE, function (who, what) return "pass", who, what end},
	{ LOOT_ROLL_ROLLED_GREED, function (value, what, who) return "roll", who, what, value, "greed" end},
	{ LOOT_ROLL_ROLLED_NEED, function (value, what, who) return "roll", who, what, value, "need" end},
	{ LOOT_ROLL_YOU_WON, function (what) return "won", player, what end},
	{ LOOT_ROLL_WON, function (who, what) return "won", who, what end},
	{ LOOT_ROLL_YOU_WON_NO_SPAM_GREED, function (count, what) return "won", player, what, "greed" end},
	{ LOOT_ROLL_WON,_NO_SPAM_GREED, function (who, count, what) return "won", who, what, "greed" end},
	{ LOOT_ROLL_YOU_WON_NO_SPAM_NEED, function (count, what) return "won", player, what, "need" end},
	{ LOOT_ROLL_WON,_NO_SPAM_NEED, function (who, count, what) return "won", who, what, "need" end},
}

local loot_handlers = {
	{ LOOT_ITEM_SELF_MULTIPLE, function (what, count) return player, what, count end},
	{ LOOT_ITEM_SELF, function (what) return player, what, 1 end},
	{ LOOT_ITEM_MULTIPLE, function (who, what, count) return who, what, count end},
	{ LOOT_ITEM, function (who, what) return who, what, 1 end},
	{ LOOT_ITEM_CREATED_SELF_MULTIPLE, function (what, count) return player, what, count, "created" end},
	{ LOOT_ITEM_CREATED_SELF, function (what) return player, what, 1, "created" end},
	{ LOOT_ITEM_PUSHED_SELF_MULTIPLE, function (what, count) return player, what, count, "pushed" end},
	{ LOOT_ITEM_PUSHED_SELF, function (what) return player, what, 1, "pushed" end},
}

local money_handlers = {
	{ YOU_LOOT_MONEY, function (coins) return player, getcoins(coins) end},
	{ LOOT_MONEY_SPLIT, function (coins) return player, getcoins(coins), "split" end},
	{ LOOT_MONEY, function (who, coins) return who, getcoins(coins) end},
}

local loot_rolls = 0
function frame:CHAT_MSG_LOOT(msg)
	if loot_rolls > 0 then
		for _, handler in ipairs(roll_handlers) do
			if handle(self, "ROLL_ITEM", handler[2], Deformat(msg, handler[1])) then
				return
			end
		end
	end
	for _, handler in ipairs(loot_handlers) do
		if handle(self, "LOOT_ITEM", handler[2], Deformat(msg, handler[1])) then
			return
		end
	end
end

function frame:CHAT_MSG_MONEY(msg)
	for _, handler in ipairs(money_handlers) do
		if handle(self, "LOOT_MONEY", handler[2], Deformat(msg, handler[1])) then
			return
		end
	end
end

frame:RegisterEvent("CHAT_MSG_LOOT")
frame:RegisterEvent("CHAT_MSG_MONEY")

function jLootz:RegisterEventNotification(event, enable)
	if enable then
		frame:RegisterEvent(event)
	else
		frame:UnregisterEvent(event)
	end
end

function jLootz:RegisterLootRoolEvents()
	function frame:START_LOOT_ROLL(id, time)
		loot_rolls = loot_rolls + 1
	end

	function frame:CANCEL_LOOT_ROLL(id)
		if loot_rolls > 0 then
			loot_rolls = loot_rolls - 1
		end
	end
	frame:RegisterEvent("START_LOOT_ROLL")
	frame:RegisterEvent("CANCEL_LOOT_ROLL")
	loot_rolls = 1
end
